<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>补齐Web前端性能分析的工具盲点 | 被删的前端游乐场</title>
    <meta name="generator" content="VuePress 1.8.2">
    
    <meta name="description" content="Just playing around">
    
    <link rel="preload" href="/front-end-playground/assets/css/0.styles.6ad2a9ca.css" as="style"><link rel="preload" href="/front-end-playground/assets/js/app.1e2670bf.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/2.38d016d1.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/3.e3f029cb.js" as="script"><link rel="preload" href="/front-end-playground/assets/js/29.af157f0c.js" as="script">
    <link rel="stylesheet" href="/front-end-playground/assets/css/0.styles.6ad2a9ca.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/front-end-playground/" class="home-link router-link-active"><!----> <span class="site-name">被删的前端游乐场</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端领域</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/front-end-work/" class="nav-link">前端与工作</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end-playground/" class="nav-link">概述</a></div><div class="nav-item"><a href="/front-end-playground/front-end-basic/" class="nav-link router-link-active">前端领域</a></div><div class="nav-item"><a href="/front-end-playground/vue/" class="nav-link">Vue学习</a></div><div class="nav-item"><a href="/front-end-playground/wxapp/" class="nav-link">小程序学习</a></div><div class="nav-item"><a href="/front-end-playground/front-end-others/" class="nav-link">百家齐放</a></div><div class="nav-item"><a href="/front-end-playground/front-end-addon/" class="nav-link">前端的进击</a></div><div class="nav-item"><a href="/front-end-playground/front-end-work/" class="nav-link">前端与工作</a></div><div class="nav-item"><a href="/front-end-playground/faq.html" class="nav-link">FAQ</a></div> <a href="https://github.com/godbasin/front-end-playground" target="_blank" rel="noopener noreferrer" class="repo-link">
    Github
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0" style="padding-top:10px;"><div class="kitty-main" data-v-2b653b36><span class="stand" data-v-2b653b36></span> <div class="cat" data-v-2b653b36><div class="body" data-v-2b653b36></div> <div class="head" data-v-2b653b36><div class="ear" data-v-2b653b36></div> <div class="ear" data-v-2b653b36></div></div> <div class="face" data-v-2b653b36><div class="nose" data-v-2b653b36></div> <div class="whisker-container" data-v-2b653b36><div class="whisker" data-v-2b653b36></div> <div class="whisker" data-v-2b653b36></div></div> <div class="whisker-container" data-v-2b653b36><div class="whisker" data-v-2b653b36></div> <div class="whisker" data-v-2b653b36></div></div></div> <div class="tail-container" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36><div class="tail" data-v-2b653b36></div></div></div></div></div></div></div></div></div></div> <p class="sidebar-heading open"><span>前端架构</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/front-end-playground/front-end-basic/deep-learning/module-seperate.html" class="sidebar-link">谈谈依赖和解耦</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/trace-stash.html" class="sidebar-link">大型前端项目要怎么跟踪和分析函数调用链</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/build-application.html" class="sidebar-link">前端构建大型应用</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/reactive-programing.html" class="sidebar-link">响应式编程在前端领域的应用</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/vscode-event.html" class="sidebar-link">VSCode 源码解读：事件系统设计</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/vscode-ipc.html" class="sidebar-link">VSCode 源码解读：IPC通信机制</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/online-doc-network.html" class="sidebar-link">在线文档的网络层设计思考</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html" aria-current="page" class="active sidebar-link">补齐Web前端性能分析的工具盲点</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html#lighthouse" class="sidebar-link">Lighthouse</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html#performance-面板" class="sidebar-link">Performance 面板</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html#合成监控" class="sidebar-link">合成监控</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html#真实用户监控" class="sidebar-link">真实用户监控</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html#使用-lighthouse" class="sidebar-link">使用 Lighthouse</a></li><li class="sidebar-sub-header"><a href="/front-end-playground/front-end-basic/deep-learning/front-end-performance-analyze.html#chrome-devtools-protocol" class="sidebar-link">Chrome DevTools Protocol</a></li></ul></li><li><a href="/front-end-playground/front-end-basic/deep-learning/monitor-and-report.html" class="sidebar-link">前端监控体系搭建</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/why-spreadsheet-app-excited.html" class="sidebar-link">在线Excel项目到底有多刺激</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/task-runner-design.html" class="sidebar-link">如何设计一个任务管理器</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/network-design-responsibility-driven-design.html" class="sidebar-link">在线文档的网络层开发思考--职责驱动设计</a></li><li><a href="/front-end-playground/front-end-basic/deep-learning/network-design-dependency-decoupling.html" class="sidebar-link">在线文档的网络层开发思考--依赖关系梳理</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>前端深入理解</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0" style="padding-top:;"><!----> <p class="sidebar-heading"><span>前端入门</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>最近依然在研究大型项目，而大型项目最容易遇到的问题便是性能问题。一般来说，当我们遇到性能瓶颈的时候，才会开始去进行相应的分析。分析的方向除了业务本身的特点相关之外，常见的我们还可以借助一些工具来发现问题。本文一起来研究下，前端性能分析可以怎么走~</p> <h1 id="前端性能分析工具-chrome-devtools"><a href="#前端性能分析工具-chrome-devtools" class="header-anchor">#</a> 前端性能分析工具（Chrome DevTools）</h1> <p>一般来说，前端的性能分析通常可以从<strong>时间</strong>和<strong>空间</strong>两个角度来进行：</p> <ul><li><strong>时间</strong>：常见耗时，如页面加载耗时、渲染耗时、网络耗时、脚本执行耗时等</li> <li><strong>空间</strong>：资源占用，包括 CPU 占用、内存占用、本地缓存占用等</li></ul> <p>那么，下面来看看有哪些常见的工具可以借来用用。由于我们的网页基本上跑在浏览器中，所以基本上大多数的工具都来源于浏览器自身提供，首当其冲的当然是 <a href="https://developers.google.com/web/tools/chrome-devtools" target="_blank" rel="noopener noreferrer">Chrome DevTools<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。本文我们也主要围绕 Chrome DevTools 来进行说明。</p> <h2 id="lighthouse"><a href="#lighthouse" class="header-anchor">#</a> Lighthouse</h2> <p><a href="https://github.com/GoogleChrome/lighthouse" target="_blank" rel="noopener noreferrer">Lighthouse<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 的前身是 Chrome DevTools 面板中的 Audits。在 Chrome 60 之前的版本中, 这个面板只包含网络使用率和页面性能两个测量类别，从 Chrome 60 版本开始， Audits 面板已经被 Lighthouse 的集成版取代。而在最新版本的 Chrome 中，则需要单独安装 Lighthouse 拓展程序来使用，也可以通过脚本来使用。</p> <h3 id="架构"><a href="#架构" class="header-anchor">#</a> 架构</h3> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/front-end-performance-analyze_7.png" alt="Lighthouse 架构"></p> <p>下面是 Lighthouse 的组成部分：</p> <ul><li>驱动（Driver）：和 <a href="https://chromedevtools.github.io/devtools-protocol/" target="_blank" rel="noopener noreferrer">Chrome Debugging Protocol<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 进行交互的接口</li> <li>收集器（Gatherers）：使用驱动程序收集页面的信息，收集器的输出结果被称为 Artifact</li> <li>审查器（Audits）：将 Artifact 作为输入，审查器会对其运行测试，然后分配通过/失败/得分的结果</li> <li>报告（Report）：将审查的结果分组到面向用户的报告中（如最佳实践），对该部分应用加权和总体然后得出评分</li></ul> <h3 id="主要功能"><a href="#主要功能" class="header-anchor">#</a> 主要功能</h3> <p>Lighthouse 会在一系列的测试下运行网页，比如不同尺寸的设备和不同的网络速度。它还会检查页面对辅助功能指南的一致性，例如颜色对比度和 ARIA 最佳实践。</p> <p>在比较短的时间内，Lighthouse 可以给出这样一份报告（可将报告生成为 JSON 或 HTML）：</p> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/front-end-performance-analyze_2.png" alt="Lighthouse 架构"></p> <p>这份报告从 5 个方面来分析页面： <strong>性能</strong>、<strong>辅助功能</strong>、<strong>最佳实践</strong>、<strong>搜索引擎优化</strong>和 <strong>PWA</strong>。像性能方面，会给出一些常见的耗时统计。除此以外，还会给到一些详细的优化方向。</p> <p>如果你希望短时间内对你的网站进行较全面的评估，可以使用 Lighthouse 来跑一下分数，确定大致的优化方向。</p> <h2 id="performance-面板"><a href="#performance-面板" class="header-anchor">#</a> Performance 面板</h2> <p><a href="https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference" target="_blank" rel="noopener noreferrer">Performance<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 面板同样有个前身，叫 <a href="https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool?hl=zh-cn" target="_blank" rel="noopener noreferrer">Timeline<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。该面板用于记录和分析<strong>运行时性能</strong>，运行时性能是页面运行时（而不是加载）的性能。</p> <h3 id="使用步骤"><a href="#使用步骤" class="header-anchor">#</a> 使用步骤</h3> <p>Performance 面板功能特别多，具体的分析也可以单独讲一篇了。这里我们简单说一下使用的步骤：</p> <ol><li>在隐身模式下打开 Chrome。隐身模式可确保 Chrome 以干净状态运行，例如浏览器的扩展可能会在性能评估中产生影响。</li> <li>在 DevTools 中，单击“Performance”选项卡，并进行一些基础配置（更多参考<a href="https://developers.google.com/web/tools/chrome-devtools/evaluate-performance" target="_blank" rel="noopener noreferrer">官方说明<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>）。</li> <li>按照提示单击记录，开始记录。进行完相应的操作之后，点击停止。</li> <li>当页面运行时，DevTools 捕获性能指标。停止记录后，DevTools 处理数据，然后在 Performance 面板上显示结果。</li></ol> <h3 id="主要功能-2"><a href="#主要功能-2" class="header-anchor">#</a> 主要功能</h3> <p>关于 Performance 怎么使用的文章特别多，大家网上随便搜一下就能搜到。一般来说，主要使用以下功能：</p> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/front-end-performance-analyze_5.jpg" alt=""></p> <ul><li><strong>查看 FPS 图表</strong>：当在 FPS 上方看到红色条形时，表示帧速率下降得太低，以至于可能损害用户体验。通常，绿色条越高，FPS 越高</li> <li><strong>查看 CPU 图表</strong>：CPU 图表在 FPS 图表下方。CPU 图表的颜色对应于性能板的底部的 Summary 选项卡</li> <li><strong>查看 火焰图</strong>：火焰图直观地表示出了内部的 CPU 分析，横轴是时间，纵轴是调用指针，调用栈最顶端的函数在最下方。启用 JS 分析器后，火焰图会显示调用的每个 JavaScript 函数，可用于分析具体函数</li> <li><strong>查看 Buttom-up</strong>：此视图可以看到某些函数对性能影响最大，并能够检查这些函数的调用路径</li></ul> <p>具体要怎么定位某些性能瓶颈，可以参考<a href="https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference" target="_blank" rel="noopener noreferrer">官方文档系列文章<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，这里就不详细介绍啦。</p> <h3 id="performance-monitor"><a href="#performance-monitor" class="header-anchor">#</a> Performance Monitor</h3> <p>打开 Chrome 控制台后，按组合键<code>ctrl + p</code>(Mac 快捷键为<code>command + p</code>)，输入<code>&gt; Show Performance Monitor</code>，就可以打开 Performance Monitor 性能监视器。主要的监控指标包括：</p> <ul><li>CPU usage：CPU 占用率</li> <li>JS head size：JS 内存使用大小</li> <li>DOM Nodes：内存中挂载的 DOM 节点个数</li> <li>JS event listeners：事件监听数</li> <li>...：其他等等</li></ul> <p>大多数情况下，我们在进行性能优化的时候，使用上面一些工具也足以确定大致的优化方向。更多的细节和案例，就不在这里详述了。</p> <h1 id="前端性能监控"><a href="#前端性能监控" class="header-anchor">#</a> 前端性能监控</h1> <p>除了具体的性能分析和定位，我们也经常需要对业务进行性能监控。前端性能监控包括两种方式：合成监控（Synthetic Monitoring，SYN）、真实用户监控（Real User Monitoring，RUM）。</p> <h2 id="合成监控"><a href="#合成监控" class="header-anchor">#</a> 合成监控</h2> <p>合成监控就是在一个模拟场景里，去提交一个需要做性能审计的页面，通过一系列的工具、规则去运行你的页面，提取一些性能指标，得出一个审计报告。例如上面介绍的 Lighthouse 就是合成监控。</p> <p>合成监控的使用场景不多，一般可能出现在开发和测试的过程中，例如结合流水线跑性能报告、定位性能问题时本地跑的一些简单任务分析等。该方式的优点显而易见：</p> <ul><li>可采集更丰富的数据指标，例如结合 <a href="https://chromedevtools.github.io/devtools-protocol/" target="_blank" rel="noopener noreferrer">Chrome Debugging Protocol<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 获取到的数据</li> <li>较成熟的解决方案和工具，实现成本低</li> <li>不影响真实用户的性能体验</li></ul> <h2 id="真实用户监控"><a href="#真实用户监控" class="header-anchor">#</a> 真实用户监控</h2> <p>真实用户监控，就是用户在我们的页面上访问，访问之后就会产生各种各样的性能指标。我们在用户访问结束的时候，把这些性能指标上传到我们的日志服务器上，进行数据的提取清洗加工，最后在我们的监控平台上进行展示的一个过程。</p> <p>我们提及前端监控的时候，大多数都包括了真实用户监控。常见的一些性能监控包括加载耗时、DOM 渲染耗时、接口耗时统计等，而对于页面加载过程，可以看到它被定义成了很多个阶段：</p> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/front-end-performance-analyze_6.png" alt="RUM 性能模型"></p> <p>而我们要做的，则是在力所能及的地方进行打点、计算、采集、上报，该过程常常需要借助 Performance Timeline API。将需要的数据发送到服务端，然后再对这些数据进行处理，最终通过可视化等方式进行监控。因此，真实用户监控往往需要结合业务本身的前后端架构设计来建设，其优点也比较容易理解：</p> <ul><li>完全还原真实场景，减去模拟成本</li> <li>数据样本足够抹平个体的差异</li> <li>采集数据可用于更多场景的分析和优化</li></ul> <p>对比合成监控，真实用户监控在有些场景下无法拿到更多的性能分析数据（例如具体哪里 CPU 占用、内存占用高），因此更多情况下作为优化效果来参考。这些情况下，具体的分析和定位可能还是得依赖合成监控。</p> <p>但真实用户监控也有自身的优势，例如 TCP、DNS 连接耗时过高，在各种环境下的一些运行耗时问题，合成监控是很难发现的。</p> <h1 id="性能分析自动化"><a href="#性能分析自动化" class="header-anchor">#</a> 性能分析自动化</h1> <p>我们在开发过程中，也常常需要进行性能分析。而前端的性能分析上手成本也不低，除了基本的页面加载耗时、网络耗时，更具体的定位往往需要结合前面介绍的 Performance 面板、FPS、CPU、火焰图等一点点来分析。</p> <p>如果这一块想要往自动化方向发展，我们可以怎么做呢？</p> <h2 id="使用-lighthouse"><a href="#使用-lighthouse" class="header-anchor">#</a> 使用 Lighthouse</h2> <p>前面也有介绍 Lighthouse，它提供了脚本的方式使用。因此，我们可以通过自动化任务跑脚本的方式，使用 Lighthouse 跑分析报告，通过对比以往的数据来进行功能变更、性能优化等场景的性能回归。</p> <p>使用 Lighthouse 的优势在于开发成本低，只需要按照<a href="https://github.com/GoogleChrome/lighthouse/blob/master/docs/configuration.md" target="_blank" rel="noopener noreferrer">官方提供的配置<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>来调整、获取自己需要的一些数据，就可以快速接入较全面的 Lighthouse 拥有的性能分析能力。</p> <p>不过由于 Lighthouse 同样基于 CDP(Chrome DevTools Protocol)，因此除了实现成本降低了，CDP 缺失的一些能力它也一样会缺失。</p> <h2 id="chrome-devtools-protocol"><a href="#chrome-devtools-protocol" class="header-anchor">#</a> Chrome DevTools Protocol</h2> <p><a href="https://chromedevtools.github.io/devtools-protocol/" target="_blank" rel="noopener noreferrer">Chrome DevTools Protocol<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 允许第三方对基于 Chrome 的 Web 应用程序进行检测、检查、调试、分析等。有了这个协议，我们就可以自己开发工具获取 Chrome 的数据了。</p> <h3 id="认识-chrome-devtools-协议"><a href="#认识-chrome-devtools-协议" class="header-anchor">#</a> 认识 Chrome DevTools 协议</h3> <p>Chrome DevTools 协议基于 WebSocket，利用 WebSocket 建立连接 DevTools 和浏览器内核的快速数据通道。</p> <p>我们使用的 Chrome DevTools 其实也是一个 Web 应用。我们使用 DevTools 的时候，浏览器内核 Chromium 本身会作为一个服务端，我们看到的浏览器调试工具界面，通过 Websocket 和 Chromium 进行通信。建立过程如下：</p> <ol><li>DevTools 将作为 Web 应用程序，Chromium 作为服务端提供连接。</li> <li>通过 HTTP 提取 HTML、JavaScript 和 CSS 文件。</li> <li>资源加载后，DevTools 会建立与浏览器的 Websocket 连接，并开始交换 JSON 消息。</li></ol> <p>同样的，当我们通过 DevTools 从 Windows、Mac 或 Linux 计算机远程调试 Android 设备上的实时内容时，使用的也是该协议。当 Chromium 以一个<code>--remote-debugging-port=0</code>标志启动时，它将启动 Chrome DevTools 协议服务器。</p> <h3 id="chrome-devtools-协议域划分"><a href="#chrome-devtools-协议域划分" class="header-anchor">#</a> Chrome DevTools 协议域划分</h3> <p>Chrome DevTools协议具有与浏览器的许多不同部分（例如页面、Service Worker 和扩展程序）进行交互的 API。该协议把不同的操作划分为了不同的域（domain），每个域负责不同的功能模块。比如<code>DOM</code>、<code>Debugger</code>、<code>Network</code>、<code>Console</code>和<code>Performance</code>等，可以理解为 DevTools 中的不同功能模块。</p> <p>使用该协议我们可以：</p> <ul><li>获取 JS 的 Runtime 数据，常用的如<code>window.performance</code>和<code>window.chrome.loadTimes()</code>等</li> <li>获取<code>Network</code>及<code>Performance</code>数据，进行自动性能分析</li> <li>使用 <a href="https://github.com/GoogleChrome/lighthouse/blob/master/docs/puppeteer.md" target="_blank" rel="noopener noreferrer">Puppeteer<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 的 <a href="https://pptr.dev/#?product=Puppeteer&amp;version=v1.13.0&amp;show=api-class-cdpsession" target="_blank" rel="noopener noreferrer">CDPSession<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，与浏览器的协议通信会变得更加简单</li></ul> <h3 id="与性能相关的域"><a href="#与性能相关的域" class="header-anchor">#</a> 与性能相关的域</h3> <p>本文讲性能分析相关，因此这里我们只关注和性能相关的域。</p> <p><strong>1. Performance。</strong>
从<code>Performance</code>域中<code>Performance.getMetrics()</code>可以拿到获取运行时性能指标包括：</p> <ul><li><code>Timestamp</code>: 采取度量样本的时间戳</li> <li><code>Documents</code>: 页面中的文档数</li> <li><code>Frames</code>: 页面中的帧数</li> <li><code>JSEventListeners</code>: 页面中的事件数</li> <li><code>Nodes</code>: 页面中的 DOM 节点数</li> <li><code>LayoutCount</code>: 全部或部分页面布局的总数</li> <li><code>RecalcStyleCount</code>: 页面样式重新计算的总数</li> <li><code>LayoutDuration</code>: 所有页面布局的合并持续时间</li> <li><code>RecalcStyleDuration</code>: 所有页面样式重新计算的总持续时间</li> <li><code>ScriptDuration</code>:  JavaScript 执行的持续时间</li> <li><code>TaskDuration</code>: 浏览器执行的所有任务的合并持续时间</li> <li><code>JSHeapUsedSize</code>: 使用的 JavaScript 栈大小</li> <li><code>JSHeapTotalSize</code>: JavaScript 栈总大小</li></ul> <p><strong>2. Tracing。</strong> <code>Tracing</code>域可获取页面加载的 DevTools 性能跟踪。可以使用<code>Tracing.start</code>和<code>Tracing.stop</code>创建可在 Chrome DevTools 或时间轴查看器中打开的跟踪文件。</p> <p>我们能看到生成的 JSON 文件长这样：
<img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/front-end-performance-analyze_8.png" alt=""></p> <p>这样的 JSON 文件，我们可以丢到 <a href="https://chromedevtools.github.io/timeline-viewer/" target="_blank" rel="noopener noreferrer">DevTools Timeline Viewer<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 中，可以看到对应的时间轴和火焰图：</p> <p><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/front-end-performance-analyze_9.jpg" alt=""></p> <p><strong>3. Runtime。</strong> <code>Runtime</code>域通过远程评估和镜像对象暴露 JavaScript 的运行时。可以通过<code>Runtime.getHeapUsage</code>获取 JavaScript 栈的使用情况，通过<code>Runtime.evaluate</code>计算全局对象的表达式，通过<code>Runtime.queryObjects</code>迭代 JavaScript 栈并查找具有给定原型的所有对象（可用于计算原型链中某处具有相同原型的所有对象，衡量 JavaScript 内存泄漏）。</p> <p>除了上面介绍的这些，还有<code>Network</code>可以分析网络相关的性能，以及其他可能涉及 DOM 节点、JS 执行等各种各样的数据分析，更多的可能需要大家自己去研究了。</p> <h3 id="自动化性能分析"><a href="#自动化性能分析" class="header-anchor">#</a> 自动化性能分析</h3> <p>通过使用 Chrome DevTools 协议，我们可以获取 DevTools 提供的很多数据，包括网络数据、性能数据、运行时数据。</p> <p>对于如何使用该协议，其实已经有很多大神针对这个协议封装出不同语言的库，包括 Node.js、Python、Java等，可以根据需要在 <a href="https://github.com/ChromeDevTools/awesome-chrome-devtools#chrome-devtools-protocol" target="_blank" rel="noopener noreferrer">awesome-chrome-devtools<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 这个项目中找到。</p> <p>至于我们到底能拿到怎样的数据，可以做到怎样的自动化程度，就不在本文里讲述啦，后面有机会再开篇文章详细讲讲。</p> <h1 id="参考"><a href="#参考" class="header-anchor">#</a> 参考</h1> <ul><li><a href="https://www.zcfy.cc/article/the-new-chrome-devtool-feature-you-want-to-know-about-3318.html" target="_blank" rel="noopener noreferrer">你一定要知道的 Chrome DevTool 新功能<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://juejin.im/post/6844904045774110733" target="_blank" rel="noopener noreferrer">前端性能分析利器-Chrome性能分析&amp;性能监视器<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://www.infoq.cn/article/Dxa8aM44oz*Lukk5Ufhy" target="_blank" rel="noopener noreferrer">蚂蚁金服如何把前端性能监控做到极致?<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://testerhome.com/topics/15817" target="_blank" rel="noopener noreferrer">chrome devtools protocol——Web 性能自动化实践介绍<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://chromedevtools.github.io/devtools-protocol/" target="_blank" rel="noopener noreferrer">Chrome DevTools Protocol<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://addyosmani.com/blog/puppeteer-recipes/#measuring-memory-leaks" target="_blank" rel="noopener noreferrer">Web Performance Recipes With Puppeteer<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul> <h1 id="结束语"><a href="#结束语" class="header-anchor">#</a> 结束语</h1> <p>前端性能分析相关的文章不算多，而由于性能分析本身的场景就跟业务特性结合比较紧密，可以用来借鉴的内容、较统一的解决方案也不多。而性能的监控、自动化等方向的介绍比较少，也希望这篇文章能给到你们一些方向吧~</p></div> <!----> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/godbasin/front-end-playground/edit/sourcecode/docs/front-end-basic/deep-learning/front-end-performance-analyze.md" target="_blank" rel="noopener noreferrer">帮阿猪改善此页面！</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <!----> <blockquote>部分文章中使用了一些网站的截图，如果涉及侵权，请告诉我删一下谢谢~</blockquote> <div style="margin-top:30px;"><div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-sm-0 el-col-md-2 el-col-lg-4" style="padding-left:10px;padding-right:10px;display:block;"><div style="width:1px;height:1px;"></div></div> <div class="el-col el-col-24 el-col-sm-24 el-col-md-18 el-col-lg-16" style="padding-left:10px;padding-right:10px;"><div class="el-card box-card is-always-shadow"><div class="el-card__header"><div class="clearfix"><span>温馨提示喵</span></div></div><div class="el-card__body"> <div class="el-row" style="margin-left:-10px;margin-right:-10px;"><div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="el-image"><div class="image-slot"><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/loading.gif" style="width:100%;"></div><!----></div></div> <div class="el-col el-col-24 el-col-xs-24 el-col-sm-12" style="padding-left:10px;padding-right:10px;"><div class="copyright-text"><div>本文版权归作者所有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</div> <div>出处：被删的前端游乐场</div> <div>作者：<a href="https://github.com/godbasin" target="_blank">被删</a></div></div></div></div></div></div></div></div></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/front-end-playground/front-end-basic/deep-learning/online-doc-network.html" class="prev">
          在线文档的网络层设计思考
        </a></span> <span class="next"><a href="/front-end-playground/front-end-basic/deep-learning/monitor-and-report.html">
          前端监控体系搭建
        </a>
        →
      </span></p></div>  <div class="gitalk-container theme-default-content"><div id="gitalk-container" class="content"></div></div></main> <div id="kitty-container"><span><div role="tooltip" id="el-popover-4217" aria-hidden="true" class="el-popover el-popper" style="width:undefinedpx;display:none;"><!----><img src="https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/2code2.jpg" class="image"> <div class="text">牡羊猪的猫粮罐</div> </div><span class="el-popover__reference-wrapper"><div id="kitty" style="background:url(https://github-imglib-1255459943.cos.ap-chengdu.myqcloud.com/assets/img/kitty2.svg);"></div></span></span> <div class="el-dialog__wrapper" style="display:none;"><div role="dialog" aria-modal="true" aria-label="牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）" class="el-dialog" style="margin-top:15vh;"><div class="el-dialog__header"><span class="el-dialog__title">牡羊猪是这样渐渐胖成猪的喵（点击图片可以切换噢）</span><button type="button" aria-label="Close" class="el-dialog__headerbtn"><i class="el-dialog__close el-icon el-icon-close"></i></button></div><!----><!----></div></div></div></div><div class="global-ui"></div></div>
    <script src="/front-end-playground/assets/js/app.1e2670bf.js" defer></script><script src="/front-end-playground/assets/js/2.38d016d1.js" defer></script><script src="/front-end-playground/assets/js/3.e3f029cb.js" defer></script><script src="/front-end-playground/assets/js/29.af157f0c.js" defer></script>
  </body>
</html>
